package com.alipay.api.internal.util.json;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public abstract class JSONReader {

   private static final Object OBJECT_END = new Object();
   private static final Object ARRAY_END = new Object();
   private static final Object COLON = new Object();
   private static final Object COMMA = new Object();
   public static final int FIRST = 0;
   public static final int CURRENT = 1;
   public static final int NEXT = 2;
   private static Map escapes = new HashMap();
   private CharacterIterator it;
   private char c;
   private Object token;
   private StringBuffer buf = new StringBuffer();


   private char next() {
      this.c = this.it.next();
      return this.c;
   }

   private void skipWhiteSpace() {
      while(Character.isWhitespace(this.c)) {
         this.next();
      }

   }

   public Object read(CharacterIterator ci, int start) {
      this.it = ci;
      switch(start) {
      case 0:
         this.c = this.it.first();
         break;
      case 1:
         this.c = this.it.current();
         break;
      case 2:
         this.c = this.it.next();
      }

      return this.read();
   }

   public Object read(CharacterIterator it) {
      return this.read(it, 2);
   }

   public Object read(String string) {
      return this.read(new StringCharacterIterator(string), 0);
   }

   private Object read() {
      this.skipWhiteSpace();
      char ch = this.c;
      this.next();
      switch(ch) {
      case 34:
         this.token = this.string();
         break;
      case 44:
         this.token = COMMA;
         break;
      case 58:
         this.token = COLON;
         break;
      case 91:
         this.token = this.array();
         break;
      case 93:
         this.token = ARRAY_END;
         break;
      case 102:
         this.next();
         this.next();
         this.next();
         this.next();
         this.token = Boolean.FALSE;
         break;
      case 110:
         this.next();
         this.next();
         this.next();
         this.token = null;
         break;
      case 116:
         this.next();
         this.next();
         this.next();
         this.token = Boolean.TRUE;
         break;
      case 123:
         this.token = this.object();
         break;
      case 125:
         this.token = OBJECT_END;
         break;
      default:
         this.c = this.it.previous();
         if(Character.isDigit(this.c) || this.c == 45) {
            this.token = this.number();
         }
      }

      return this.token;
   }

   private Object object() {
      HashMap ret = new HashMap();
      Object key = this.read();

      while(this.token != OBJECT_END) {
         this.read();
         if(this.token != OBJECT_END) {
            ret.put(key, this.read());
            if(this.read() == COMMA) {
               key = this.read();
            }
         }
      }

      return ret;
   }

   private Object array() {
      ArrayList ret = new ArrayList();
      Object value = this.read();

      while(this.token != ARRAY_END) {
         ret.add(value);
         if(this.read() == COMMA) {
            value = this.read();
         }
      }

      return ret;
   }

   private Object number() {
      byte length = 0;
      boolean isFloatingPoint = false;
      this.buf.setLength(0);
      if(this.c == 45) {
         this.add();
      }

      int length1 = length + this.addDigits();
      if(this.c == 46) {
         this.add();
         length1 += this.addDigits();
         isFloatingPoint = true;
      }

      if(this.c == 101 || this.c == 69) {
         this.add();
         if(this.c == 43 || this.c == 45) {
            this.add();
         }

         this.addDigits();
         isFloatingPoint = true;
      }

      String s = this.buf.toString();
      return isFloatingPoint?(length1 < 17?Double.valueOf(s):new BigDecimal(s)):(length1 < 19?Long.valueOf(s):new BigInteger(s));
   }

   private int addDigits() {
      int ret;
      for(ret = 0; Character.isDigit(this.c); ++ret) {
         this.add();
      }

      return ret;
   }

   private Object string() {
      this.buf.setLength(0);

      while(this.c != 34) {
         if(this.c == 92) {
            this.next();
            if(this.c == 117) {
               this.add(this.unicode());
            } else {
               Object value = escapes.get(Character.valueOf(this.c));
               if(value != null) {
                  this.add(((Character)value).charValue());
               }
            }
         } else {
            this.add();
         }
      }

      this.next();
      return this.buf.toString();
   }

   private void add(char cc) {
      this.buf.append(cc);
      this.next();
   }

   private void add() {
      this.add(this.c);
   }

   private char unicode() {
      int value = 0;

      for(int i = 0; i < 4; ++i) {
         switch(this.next()) {
         case 48:
         case 49:
         case 50:
         case 51:
         case 52:
         case 53:
         case 54:
         case 55:
         case 56:
         case 57:
            value = (value << 4) + this.c - 48;
         case 58:
         case 59:
         case 60:
         case 61:
         case 62:
         case 63:
         case 64:
         case 71:
         case 72:
         case 73:
         case 74:
         case 75:
         case 76:
         case 77:
         case 78:
         case 79:
         case 80:
         case 81:
         case 82:
         case 83:
         case 84:
         case 85:
         case 86:
         case 87:
         case 88:
         case 89:
         case 90:
         case 91:
         case 92:
         case 93:
         case 94:
         case 95:
         case 96:
         default:
            break;
         case 65:
         case 66:
         case 67:
         case 68:
         case 69:
         case 70:
            value = (value << 4) + this.c - 75;
            break;
         case 97:
         case 98:
         case 99:
         case 100:
         case 101:
         case 102:
            value = (value << 4) + this.c - 107;
         }
      }

      return (char)value;
   }

   static {
      escapes.put(Character.valueOf('\"'), Character.valueOf('\"'));
      escapes.put(Character.valueOf('\\'), Character.valueOf('\\'));
      escapes.put(Character.valueOf('/'), Character.valueOf('/'));
      escapes.put(Character.valueOf('b'), Character.valueOf('\b'));
      escapes.put(Character.valueOf('f'), Character.valueOf('\f'));
      escapes.put(Character.valueOf('n'), Character.valueOf('\n'));
      escapes.put(Character.valueOf('r'), Character.valueOf('\r'));
      escapes.put(Character.valueOf('t'), Character.valueOf('\t'));
   }
}
